/**
 * @(#) Coordinate.java
 */

package org.vsg.stock.core.indicator.coordinate;

import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import org.vsg.stock.core.KLineStock.Attribute;
import org.vsg.stock.core.domain.StockDailyKLine;
import org.vsg.stock.core.domain.StockDailyKLinePK;
import org.vsg.stock.core.indicator.coordinate.origpoint.SimpleOriginalDataPoint;
import org.vsg.stock.core.indicator.coordinate.shape.ShapeEquation;
import org.vsg.stock.core.kline.DailyKLineStock;
import org.vsg.stock.core.utils.StockDateUtilExtension;

/**
 * @param <T>
 * @author Bill vison
 * 
 */
public class DefaultCoordinate<T extends DailyKLineStock> extends AbstractCoordinate
{
	
	public DefaultCoordinate() {
		
	}


	static private DecimalFormat nf = new DecimalFormat("##0.0000");		
	
	private List<ShapeEquation> matchPattern = new Vector<ShapeEquation>();
	
	private List<Processor> procs  = new Vector<Processor>();

	

	
	/**
	 * @param klineData
	 */
	public void process(List<T> klineData )
	{
		/*
		if ( procs != null) {
			
			for (Processor processor : procs) {
				List<ShapeEquation> shapePatternList = processor.process(context, klineData);
				if ( shapePatternList != null) {
					//matchPattern.add(shapePattern);
				}
			}
		}
		*/
	}

	
	


	/**
	 * @return 
	 */
	public List<ShapeEquation> outputPattern( )
	{
		return null;
	}

	/**
	 * @param processors
	 */
	public void setProcessors(List<Processor> processors) {
		procs = processors;
	}


	/**
	 * add processor for the handle shape
	 * @param processor
	 */
	public void addProcessor(Processor processor) {
		if (!procs.contains( processor )) {
			procs.add(processor);
		}
	}
	
	public boolean removeProcessor(Processor processor) {
		return procs.remove(processor);
	}
	
	private StockDateUtilExtension stkDateUtilExtension;
	
	

	public StockDateUtilExtension getStkDateUtilExtension() {
		return stkDateUtilExtension;
	}

	public void setStkDateUtilExtension(StockDateUtilExtension stkDateUtilExtension) {
		this.stkDateUtilExtension = stkDateUtilExtension;
	}


	
	@Override
	public CoordinatePoint convertToCoordinatePoint(OriginalDataPoint relaPoint) {

		double x = this.getXValueFromODP( relaPoint.getXvalue() );
		
		double y = this.getYValueFromODP( relaPoint.getYvalue() );

		y = Double.parseDouble( nf.format( y ) );
				
		// --- set the CoordinatePoint ----
		SimpleCoordinatePoint coordinatePoint = new SimpleCoordinatePoint();
		coordinatePoint.setXvalue( x );
		coordinatePoint.setYvalue( y );
		
		return coordinatePoint;				

	}

	
	
	
	@Override
	public OriginalDataPoint restoreToOriginalDataPoint(CoordinatePoint point) {
		UnitDefinition ud = this.getContext().getUnitDefinition();
		
		double xInCoord = Double.parseDouble( nf.format( point.getXvalue() * ud.getXUnit()) );
		double yInCoord = Double.parseDouble( nf.format( point.getYvalue() * ud.getYUnit() ) );
		
		double absoluteXValue = this.getOriginXValueRelative() + xInCoord;
		double absoluteYValue = this.getOriginYValueRelative() + yInCoord;
		
		Date xDate = this.getXDateFromIndex( absoluteXValue );
		
		
		return new SimpleOriginalDataPoint(absoluteYValue , xDate);
	}





	@Override
	public List<CoordinatePoint> convertToCoordinatePoints(List klsList) {
		// TODO Auto-generated method stub
		List<CoordinatePoint> groupAll = new Vector<CoordinatePoint>();
		for (int i = 0 ; i < klsList.size() ; i++) {
			List<CoordinatePoint> aGroup = convertToCoordinatePoint((DailyKLineStock) klsList.get(i) );
			groupAll.addAll( aGroup );
		}
		return groupAll;
	}

	@Override
	public List<DailyKLineStock> restoreToKLineDate(List points) {
		
		HashMap<Date, StockDailyKLine> converMaps = new HashMap<Date, StockDailyKLine>();
		
		UnitDefinition ud = this.getContext().getUnitDefinition();
		
		List<DailyKLineStock> sdkList = new Vector<DailyKLineStock>();
		
		CoordinatePoint cp = null;
		Date currentDate = null;
		StockDailyKLinePK pk = null;
		
		for (int i = 0 ; i < points.size() ; i++) {
			cp = (CoordinatePoint) points.get( i );
			
			double xInCoord = Double.parseDouble( nf.format( cp.getXvalue() * ud.getXUnit()) );
			double yInCoord = Double.parseDouble( nf.format( cp.getYvalue() * ud.getYUnit() ) );
			double absoluteXValue = this.getOriginXValueRelative() + xInCoord;
			double absoluteYValue = this.getOriginYValueRelative() + yInCoord;
			
			currentDate = this.getXDateFromIndex( absoluteXValue );
			
			StockDailyKLine sdk = converMaps.get( currentDate);
			if ( sdk == null) {
				sdk = new StockDailyKLine();
				pk = new StockDailyKLinePK();
				pk.setDate( currentDate );
				pk.setStockCode( this.getStockCode() );
				sdk.setId( pk );
			}

			
			KLineAttributePointSupport kaps = (KLineAttributePointSupport)cp;
			Attribute klineAttribute = kaps.getKLineAttribute();

			if ( klineAttribute == Attribute.OPEN) {
				sdk.setOpen( absoluteYValue );
			}
			else if (klineAttribute == Attribute.HIGH) {
				sdk.setHigh( absoluteYValue );
			}
			else if (klineAttribute == Attribute.LOW) {
				sdk.setLow( absoluteYValue );
			}
			else if (klineAttribute == Attribute.CLOSE) {
				sdk.setHigh( absoluteYValue );
			}
			
			// --- checking all value in field ---
			
			
			converMaps.put( currentDate , sdk);
			if ( !sdkList.contains( sdk ) ) {
				sdkList.add( sdk );
			}
			
				
		}

		return sdkList;
	}

	
	
	@Override
	public List<CoordinatePoint> convertToCoordinatePoint(DailyKLineStock kl) {

		List<CoordinatePoint> result = new Vector<CoordinatePoint>();

		List<OriginalDataPoint>  pointList =  getConverter().convertKLineToCoordinatePoint(kl);

		double xValue = getXValueFromODP( kl.getDate());

		StockKLineCoordinatePoint scp = null;
		for (int i = 0 ; i < pointList.size() ; i++) {
			OriginalDataPoint odp = pointList.get( i );
			
			KLineAttributePointSupport  kap = (KLineAttributePointSupport)odp;
			
			scp = new StockKLineCoordinatePoint();
			scp.setXvalue( xValue );
			scp.setYvalue( getYValueFromODP( odp.getYvalue()) );
			scp.setKLineAttribute( kap.getKLineAttribute() );
			
			result.add( scp );
		}
		
		return result;
	}



	
	 
}
